package main

import "fmt"

type ProcessData struct {
	processName string  // 进程名称
	arriveTime  int     // 到达时间
	workTime    int     // 工作时间
	finishTime  int     // 完成时间
	turnTime    int     // 周转时间
	powerTime   float64 // 带权周转时间
	response    float64 // 响应比
}

var (
	responseList []ProcessData // 按响应比排列的进程队列
	currentTime  = 0           // 当前时间
)

func main() {
	var processList []ProcessData
	processList = append(processList, ProcessData{
		processName: "B",
		arriveTime:  1,
		workTime:    5,
	})
	processList = append(processList, ProcessData{
		processName: "A",
		arriveTime:  0,
		workTime:    20,
	})
	processList = append(processList, ProcessData{
		processName: "D",
		arriveTime:  3,
		workTime:    2,
	})
	processList = append(processList, ProcessData{
		processName: "C",
		arriveTime:  2,
		workTime:    10,
	})
	processList = sortProcessByArrive(processList)
	fmt.Println("----------计算响应比----------")
	hrn(processList)
	fmt.Println("----------计算响应比----------")
	display(responseList)
}

func hrn(processList []ProcessData) {
	// 按到达时间计算第一个进程
	currentTime = processList[0].calcProcess()
	responseList = append(responseList, processList[0])
	// 剩余队列按响应比计算
	getBigerResponse(processList[1:])
}

func getBigerResponse(processList []ProcessData) {
	for i := range processList {
		processList[i].calcProcess()
	}
	showResponse(processList)
	processList = sortProcessByResponse(processList)
	// 将当前最高响应比进程加入结果队列
	currentTime = processList[0].calcProcess()
	responseList = append(responseList, processList[0])
	// 剩余队列
	less := processList[1:]
	// 队列为空则停止
	if len(less) < 1 {
		return
	}
	// 否则继续计算剩余队列
	getBigerResponse(less)
}

// 显示hrn中的响应比
func showResponse(processList []ProcessData) {
	for _, p := range processList {
		fmt.Printf("进程%s: %3.2f  ", p.processName, p.response)
	}
	fmt.Println()
}

// 显示结果
func display(processList []ProcessData) {
	totalTurn := 0.0
	totalPower := 0.0
	for _, p := range processList {
		totalTurn += float64(p.turnTime)
		totalPower += p.powerTime
		fmt.Printf("进程名:%s 到达时间:%2d 工作时间:%2d 完成时间:%2d 周转时间:%2d 带权周转时间:%3.2f\n",
			p.processName,
			p.arriveTime,
			p.workTime,
			p.finishTime,
			p.turnTime,
			p.powerTime)
	}
  length := float64(len(processList))
  fmt.Println("平均周转时间:", totalTurn/length)
  fmt.Println("平均带权周转时间:", totalPower/length)
}

// 按到达时间升序排序
func sortProcessByArrive(processList []ProcessData) []ProcessData {
	if len(processList) <= 1 {
		return processList
	}
	var smaller []ProcessData
	var bigger []ProcessData
	current := processList[0]
	other := processList[1:]
	for _, p := range other {
		if p.arriveTime < current.arriveTime {
			smaller = append(smaller, p)
		} else {
			bigger = append(bigger, p)
		}
	}
	result := append(sortProcessByArrive(smaller), current)
	result = append(result, sortProcessByArrive(bigger)...)
	return result
}

// 根据响应比降序排序
func sortProcessByResponse(processList []ProcessData) []ProcessData {
	if len(processList) <= 1 {
		return processList
	}
	var smaller []ProcessData
	var bigger []ProcessData
	current := processList[0]
	other := processList[1:]
	for _, p := range other {
		if p.response > current.response {
			smaller = append(smaller, p)
		} else {
			bigger = append(bigger, p)
		}
	}
	result := append(sortProcessByResponse(smaller), current)
	result = append(result, sortProcessByResponse(bigger)...)
	return result
}

// 编写每个进程的计算时间方法
func (p *ProcessData) calcProcess() int {
	time := currentTime
	if currentTime < p.arriveTime {
		time = p.arriveTime
	}
	time += p.workTime
	p.finishTime = time
	p.turnTime = p.finishTime - p.arriveTime
	p.powerTime = float64(p.turnTime) / float64(p.workTime)
	p.response = float64(p.turnTime) / float64(p.workTime)
	return time
}
